package com.example.basic.web.service.pda.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.basic.exception.ServiceException;
import com.example.basic.utils.HttpUtils;
import com.example.basic.utils.IdUtils;
import com.example.basic.utils.StringUtils;
import com.example.basic.web.enums.*;
import com.example.basic.web.model.binding.BindingInfo;
import com.example.basic.web.model.device.Device;
import com.example.basic.web.model.notice.InNotice;
import com.example.basic.web.model.notice.OutNotice;
import com.example.basic.web.model.pharmIn.PharmInRecord;
import com.example.basic.web.model.pharmOut.PharmOutRecord;
import com.example.basic.web.model.pharmStock.PharmStock;
import com.example.basic.web.model.remains.RemainsInfo;
import com.example.basic.web.model.stretcher.Stretcher;
import com.example.basic.web.model.terminal.TerminalRecord;
import com.example.basic.web.response.*;
import com.example.basic.web.service.binding.BindingInfoService;
import com.example.basic.web.service.common.CommonService;
import com.example.basic.web.service.device.DeviceService;
import com.example.basic.web.service.notice.InNoticeService;
import com.example.basic.web.service.notice.OutNoticeService;
import com.example.basic.web.service.pda.PdaService;
import com.example.basic.web.service.pharmIn.PharmInRecordService;
import com.example.basic.web.service.pharmOut.PharmOutRecordService;
import com.example.basic.web.service.pharmStock.PharmStockService;
import com.example.basic.web.service.remains.RemainsInfoService;
import com.example.basic.web.service.stretcher.StretcherService;
import com.example.basic.web.service.terminal.TerminalRecordService;
import com.example.basic.web.service.transTask.TransTaskService;
import com.example.basic.web.service.zoneDepot.ZoneDepotService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.io.IOException;
import java.rmi.ServerException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static com.example.basic.utils.CheckUtil.notNull;

/**
 * <p>
 * 全局参数表 服务实现类
 * </p>
 *
 * @author zhangzq
 * @since 2023-12-08
 */
@Service
@Transactional
public class PdaServiceImpl  implements PdaService {

    @Resource
    private RemainsInfoService remainsInfoService;

    @Resource
    private BindingInfoService bindingInfoService;

    @Resource
    private InNoticeService inNoticeService;

    @Resource
    private PharmInRecordService pharmInRecordService;

    @Resource
    private HttpServletRequest request;

    @Resource
    private DeviceService deviceService;

    @Resource
    private PharmOutRecordService pharmOutRecordService;

    @Resource
    private TerminalRecordService terminalRecordService;
    @Resource
    private ZoneDepotService zoneDepotService;
    @Resource
    private PharmStockService pharmStockService;
    @Resource
    private OutNoticeService outNoticeService;

    @Resource
    private TransTaskService transTaskService;

    @Resource
    private StretcherService stretcherService;

    @Resource
    private CommonService commonService;

    /**
     * 遗体列表
     * @param searchParam 模糊搜索(拼音码,五笔码,名称)
     * @return
     */
    @Override
    public List<RemainsInfo> waitInList(String searchParam) {

        return remainsInfoService.queryByBinding(searchParam);
    }

    /**
     * 绑定信息详情
     *
     * @param deviceCode    设备编码
     * @param remainsCode
     * @return
     */
    @Override
    public BindingInfoResponse bindingDetail(String deviceCode,String remainsCode) {
        if(StringUtils.emptyParams(deviceCode,remainsCode)){
            throw new ServiceException("设备编码，遗体信息不能同时为空");
        }

        return remainsInfoService.bindingDetail(deviceCode,remainsCode);
    }

    /**
     * 遗体信息绑定
     *
     * @param deviceCode 设备编码
     * @param remainsCode 遗体编码
     * @return
     */
    @Override
    public BindingInfoResponse binding(String deviceCode, String remainsCode) {
        notNull(deviceCode,"设备编码不能为空");
        notNull(remainsCode,"遗体编码不能为空");

        //获取绑定信息详情
        BindingInfoResponse bindingInfoResponse = this.bindingDetail(deviceCode, remainsCode);

        if(bindingInfoResponse != null){
            throw new ServiceException("该遗体信息已绑定");
        }

        //生成入库通知单
        InNotice inNotice = new InNotice();
        inNotice.setDockStation(deviceCode);
        inNotice.setRemainsCode(remainsCode);
        inNotice.setOperPerson((String) request.getAttribute("userCode"));
        inNotice.setStatus(AuditEnum.ADD.getType());
        inNoticeService.batchAdd(Arrays.asList(inNotice),false);

        //添加绑定关系
        BindingInfo bindingInfo = new BindingInfo();
        bindingInfo.setDeviceCode(deviceCode);
        bindingInfo.setRemainsCode(remainsCode);
        bindingInfo.setDocumentNo(inNotice.getInNoticeCode());
        bindingInfoService.add(bindingInfo);

        //更新接驳台为占用
        deviceService.freeOrUse(deviceCode);

        return this.bindingDetail(deviceCode, remainsCode);
    }

    /**
     * 入库通知单列表
     *
     * @param queryPage
     * @param searchParam 模糊搜索(遗体名称，拼音码，五笔码)
     * @param type        类型，1-待发起，2-已发起
     * @return
     */
    @Override
    public IPage<PdaNoticeResponse> noticeList(Page<PdaNoticeResponse> queryPage, String searchParam, String type) {
        return inNoticeService.noticeList(queryPage,searchParam,type);
    }

    /**
     * 绑定信息详情
     * @param deviceCode 设备编码
     * @param remainsCode 遗体编码
     * @param status 操作类型
     * @return
     */
    @Override
    public BindingInfoResponse judgeDocument(String deviceCode, String remainsCode, String status) {
        if(StringUtils.emptyParams(deviceCode,remainsCode)){
            throw new ServiceException("设备编码,遗体编码不能同时为空");
        }

        //获取绑定信息详情
        BindingInfoResponse bindingInfoResponse = this.bindingDetail(deviceCode, remainsCode);

        //担架板入库扫码
        if(StringUtils.emptyParams(bindingInfoResponse.getDocumentNo()) && status.equals("")){
            return bindingInfoResponse;
        }

        //获取已完成的任务信息
        TerminalRecord terminalRecord = terminalRecordService.queryFinishRecord(bindingInfoResponse.getDocumentNo());

        if(terminalRecord == null){
            throw new ServiceException("单据号无效");
        }

//        if(!status.equals(terminalRecord.getInstructAddress())){
//            throw new ServiceException("功能不符");
//        }

        //单据状态
//        String documentStatus = null;
//
//        //通过单据号查询单据
//        //入库单
//        PharmInRecord pharmInRecord = pharmInRecordService.detail(bindingInfoResponse.getDocumentNo());
//        if(pharmInRecord != null){
//
//            if(status.equals("1")){
//                documentStatus = "2";
//            }else if (status.equals("2") || status.equals("3") || status.equals("4") || status.equals("5")){
//                documentStatus = "3";
//            }else if (status.equals("7")){
//                documentStatus = "4";
//            }
//            if(!pharmInRecord.getStatus().equals(documentStatus)){
//                throw new ServiceException("功能不符");
//            }
//        }
//        //出库单
//        PharmOutRecord pharmOutRecord = pharmOutRecordService.detail(bindingInfoResponse.getDocumentNo());
//        if(pharmOutRecord != null){
//            if(status.equals("1")){
//                documentStatus = "2";
//            }else if (status.equals("2") || status.equals("3") || status.equals("4") || status.equals("5")){
//                documentStatus = "3";
//            }else if (status.equals("7")){
//                documentStatus = "4";
//            }
//
//            if(!pharmOutRecord.getStatus().equals(documentStatus)){
//                throw new ServiceException("功能不符");
//            }
//        }
        return bindingInfoResponse;
    }

    /**
     * 完成任务
     * @param documentNo 单据号
     * @param remainsCode 遗体编码
     * @param status 操作类型
     * @return
     */
    @Override
    public Boolean finishInstruct(String documentNo, String remainsCode, String status) throws IOException {
        notNull(documentNo,"单据号不能为空");
        notNull(status,"操作类型不能为空");

        //获取需要执行的下一任务
        TerminalRecord nextNode = terminalRecordService.queryNextStruct(documentNo);

        if(nextNode == null){
            return true;
        }

        //单据状态
        String documentStatus = null;

        //通过单据号查询单据
        //入库单
        PharmInRecord pharmInRecord = pharmInRecordService.detail(documentNo);
        if(pharmInRecord != null && nextNode != null){
            if(status.equals("1")){
                documentStatus = "2";
            }else if (status.equals("2") || status.equals("3") || status.equals("4") || status.equals("5")){
                documentStatus = "3";
            }else if (status.equals("7")){
                documentStatus = "4";
            }
            pharmInRecord.setStatus(documentStatus);
            pharmInRecordService.update(pharmInRecord);
        }
        //出库单
        PharmOutRecord pharmOutRecord = pharmOutRecordService.detail(documentNo);
        if(pharmOutRecord != null && nextNode != null){
            if(!status.equals(nextNode.getDocumentStatus())){
                throw new ServiceException("非当前需要进行的操作");
            }
            if(status.equals("1")){
                documentStatus = "2";
            }else if (status.equals("2") || status.equals("3") || status.equals("4") || status.equals("5")){
                documentStatus = "3";
            }else if (status.equals("7")){
                documentStatus = "4";
            }
            pharmOutRecord.setStatus(documentStatus);
            pharmOutRecordService.update(pharmOutRecord);
            if(status.equals("1")){
                OutNotice outNotice = outNoticeService.detail(pharmOutRecord.getOutNoticeCode());
                PharmStock pharmStock = pharmStockService.queryByRemainsCode(outNotice.getRemainsCode());
                //更新库位为空闲
                zoneDepotService.useDepot(Arrays.asList(pharmStock.getDepotCode()),YesNoEnum.NO_FLAG.getType());
            }

        }

        if(nextNode.getOperType().contains("提升机")){
            //获取空闲提升机
            Device device = deviceService.findUnUseDockStation(nextNode.getInstructEnd(),"4");
            if(device == null){
                //获取空闲接驳台
                device = deviceService.findUnUseDockStation(nextNode.getInstructEnd(),"3");
            }

            if(device == null){
                nextNode.setStatus(InstructStatusEnum.BLOCK.getType());
                terminalRecordService.update(nextNode);

                return true;
            }
        }

        transTaskService.sendTransTask(documentNo);
        return true;
    }

    /**
     * 遗体信息详情
     * @param remainsCode
     * @return
     */
    @Override
    public BindingInfoResponse remainsInfo(String remainsCode) {
        notNull(remainsCode,"遗体信息编码不能为空");
        return remainsInfoService.remainsInfo(remainsCode);
    }

    /**
     * 入库上架
     * @param inNotice
     * @return
     */
    @Override
    public Boolean inPharm(InNotice inNotice) {
        return inNoticeService.inPharm(inNotice);
    }

    /**
     * 担架板出库
     * @param deviceCode
     * @return
     */
    @Override
    public Boolean stretcherOut(String deviceCode) throws IOException {
        notNull(deviceCode,"设备编码不能为空");

        //获取设备信息
        Device device = deviceService.detail(deviceCode);

        if(device.getStatus().equals(DeviceStatusEnum.work.getType())){
            throw new ServerException("设备已存在执行任务");
        }

        if(device == null){
            throw new ServiceException("设备编码无效");
        }

        //获取待出库担架板库位
        Stretcher stretcher = stretcherService.queryUseDepot();

        if(stretcher == null){
            throw new ServiceException("担架板已全部出库");
        }

        //更新设备为使用
        deviceService.freeOrUse(deviceCode);

        String beginPoint = "#"+stretcher.getColumnNum()+"#"+stretcher.getLayerNum();
        String taskRecordId = IdUtils.fastUUID();
        String documentNo = String.valueOf(System.currentTimeMillis());
        //开始点位
        String beginAddress = stretcher.getStretcherPoint();

        List<TerminalRecord> terminalRecordList = new ArrayList<>();

        //结束点位
        String endAddress = DeviceAddressEnum.STAGING_AREA.getType();

        //生成作业记录 担架库->暂存区->终点接驳台
        TerminalRecord terminalRecord = new TerminalRecord();
        terminalRecord.setInstructEnd(endAddress);
        terminalRecord.setInstructStart(beginAddress);
        terminalRecord.setOperType("担架板出库");
        terminalRecord.setTerminalCode(deviceCode);
        terminalRecord.setInstructTime(commonService.getDataBaseTime());
        terminalRecord.setOperPerson(request.getAttribute("userCode").toString());
        terminalRecord.setSortNo(1);
        terminalRecord.setStatus(InstructStatusEnum.IN_PROGRESS.getType());
        terminalRecord.setTaskRecordId(taskRecordId);
        terminalRecord.setDepotCode(stretcher.getId());
        terminalRecord.setDocumentNo(documentNo);
        terminalRecordList.add(terminalRecord);

        //暂存区换车
        terminalRecord = new TerminalRecord();
        terminalRecord.setOperType("换车");
        terminalRecord.setInstructStart(beginAddress);
        terminalRecord.setInstructEnd(device.getDevicePoint());
        terminalRecord.setStatus(InstructStatusEnum.WAIT.getType());
        terminalRecord.setSortNo(2);
        terminalRecord.setInstructAddress(DeviceAddressEnum.STAGING_AREA.getType());
        terminalRecord.setDocumentNo(documentNo);
        terminalRecordList.add(terminalRecord);

        terminalRecordService.batchAdd(terminalRecordList);

        //获取暂存区接驳台
        Device unUseDockStation = deviceService.findUnUseDockStation(endAddress,"3");
        if(unUseDockStation == null){
            terminalRecordList.get(0).setStatus(InstructStatusEnum.BLOCK.getType());
            terminalRecordService.update( terminalRecordList.get(0));
            return false;
        }else {
            terminalRecordList.get(0).setInstructEnd(unUseDockStation.getDevicePoint());

            //更新设备为使用状态
            deviceService.freeOrUse(unUseDockStation.getDeviceCode());
        }

        terminalRecordList.get(0).setInstructTime(commonService.getDataBaseTime());
        terminalRecordList.get(0).setStatus(InstructStatusEnum.IN_PROGRESS.getType());
        terminalRecordList.get(0).setTaskRecordId(taskRecordId);
        terminalRecordService.update( terminalRecordList.get(0));


        HttpUtils.sendPost(null,beginPoint,unUseDockStation.getDevicePoint(),taskRecordId);

        return true;
    }

    /**
     * 担架板入库
     * @param deviceCode
     * @return
     */
    @Override
    public Boolean stretcherIn(String deviceCode) throws IOException {
        notNull(deviceCode,"设备编码不能为空");

        //获取设备信息
        Device device = deviceService.detail(deviceCode);

        if(device == null){
            throw new ServiceException("设备编码无效");
        }

        //获取待入库担架板库位
        Stretcher stretcher = stretcherService.queryUnUseDepot();

        if(stretcher == null){
            throw new ServiceException("担架板库位已满");
        }

        if(stretcher.getIsUse().equals("1")){
            throw new ServerException("担架板已占用");
        }

        //更新库位为占用
        stretcher.setIsUse("1");
        stretcherService.freeOrUse(stretcher.getId());

        String endPoint = "#"+stretcher.getColumnNum()+"#"+stretcher.getLayerNum();
        String taskRecordId = IdUtils.fastUUID();

        String documentNo = "DJR"+String.valueOf(System.currentTimeMillis());

        //生成作业记录
        List<TerminalRecord> terminalRecordList = new ArrayList<>();
        TerminalRecord terminalRecord = new TerminalRecord();
        terminalRecord.setInstructEnd(DeviceAddressEnum.TRANS_HOIST.getType());
        terminalRecord.setInstructStart(device.getDevicePoint());
        terminalRecord.setOperType("担架板入库");
        terminalRecord.setTerminalCode(deviceCode);
        terminalRecord.setInstructTime(commonService.getDataBaseTime());
        terminalRecord.setOperPerson(request.getAttribute("userCode").toString());
        terminalRecord.setSortNo(1);
        terminalRecord.setStatus(InstructStatusEnum.WAIT.getType());
        terminalRecord.setDocumentNo(documentNo);
        terminalRecord.setDepotCode(stretcher.getId());
        terminalRecordList.add(terminalRecord);

        //-1中转提升机
        terminalRecord = new TerminalRecord();
        terminalRecord.setOperType("-1层提升机");
        terminalRecord.setInstructStart(DeviceAddressEnum.TRANS_HOIST.getType());
        terminalRecord.setInstructEnd(DeviceAddressEnum.STAGING_AREA.getType());
        terminalRecord.setSortNo(2);
        terminalRecord.setStatus(InstructStatusEnum.WAIT.getType());
        terminalRecord.setInstructAddress(DeviceAddressEnum.TRANS_HOIST.getType());
        terminalRecord.setDepotCode(stretcher.getId());
        terminalRecord.setDocumentNo(documentNo);
        terminalRecordList.add(terminalRecord);

        //暂存区换车
        terminalRecord = new TerminalRecord();
        terminalRecord.setOperType("换车");
        terminalRecord.setInstructStart(DeviceAddressEnum.STAGING_AREA.getType());
        terminalRecord.setInstructEnd(stretcher.getStretcherPoint());
        terminalRecord.setSortNo(3);
        terminalRecord.setInstructAddress(DeviceAddressEnum.STAGING_AREA.getType());
        terminalRecord.setStatus(InstructStatusEnum.WAIT.getType());
        terminalRecord.setDepotCode(stretcher.getId());
        terminalRecord.setDocumentNo(documentNo);
        terminalRecordList.add(terminalRecord);

        terminalRecordService.batchAdd(terminalRecordList);

        //获取-1提升机
        Device beginDevice = deviceService.findUnUseDockStation(DeviceAddressEnum.TRANS_HOIST.getType(),"4");
        if(beginDevice == null){
            terminalRecordList.get(0).setStatus(InstructStatusEnum.BLOCK.getType());
            terminalRecordService.update( terminalRecordList.get(0));
            return false;
        }else {
            terminalRecordList.get(0).setInstructEnd(beginDevice.getDevicePoint());

            //更新设备为使用状态
            deviceService.freeOrUse(beginDevice.getDeviceCode());
        }

        terminalRecordList.get(0).setInstructTime(commonService.getDataBaseTime());
        terminalRecordList.get(0).setStatus(InstructStatusEnum.IN_PROGRESS.getType());
        terminalRecordList.get(0).setTaskRecordId(taskRecordId);
        terminalRecordService.update( terminalRecordList.get(0));


        HttpUtils.sendPost(null,device.getDevicePoint(),beginDevice.getDevicePoint(),taskRecordId);

        return true;
    }

    /**
     * 临时接口
     * @param startAdress
     * @return
     * @throws IOException
     */
    @Override
    public void tempTest(String startAdress,String remainsCode) {

        Long documentNo = System.currentTimeMillis();

        List<TerminalRecord> terminalRecordList = new ArrayList<>();
        //直接火化
        TerminalRecord terminalRecord = new TerminalRecord();
        //-1层提升机->提升机接驳台->火化间提升机
        terminalRecord = new TerminalRecord();
        terminalRecord.setOperType("-1层提升机");
        terminalRecord.setRemainsCode(remainsCode);
        terminalRecord.setInstructStart(startAdress);
        terminalRecord.setInstructEnd(DeviceAddressEnum.TRANS_HOIST.getType());
        terminalRecord.setStatus("0");
        terminalRecord.setSortNo(1);
        terminalRecord.setDocumentNo(documentNo.toString());
        terminalRecord.setInstructAddress(DeviceAddressEnum.TRANS_HOIST.getType());
        terminalRecordList.add(terminalRecord);

//        beginAddress = DeviceAddressEnum.TRANS_HOIST.getType();

        terminalRecord = new TerminalRecord();
        terminalRecord.setOperType("火化间提升机");
        terminalRecord.setRemainsCode(remainsCode);
        terminalRecord.setInstructStart(DeviceAddressEnum.TRANS_HOIST.getType());
        terminalRecord.setInstructEnd(DeviceAddressEnum.CREMATION.getType());
        terminalRecord.setStatus("0");
        terminalRecord.setSortNo(2);
        terminalRecord.setDocumentNo(documentNo.toString());
        terminalRecord.setInstructAddress(DeviceAddressEnum.CREMATION.getType());
        terminalRecordList.add(terminalRecord);

        terminalRecordService.batchAdd(terminalRecordList);
    }
}